package com.wangsh.userscenter.back.controller;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import com.wangsh.userscenter.common.controller.BaseController;
import com.wangsh.userscenter.common.util.ConstatFinalUtil;
import com.wangsh.userscenter.common.util.PageInfoUtil;
import com.wangsh.userscenter.outer.service.IOuterService;
import com.wangsh.userscenter.users.pojo.AAdmins;
import com.wangsh.userscenter.users.pojo.AAdminsEnum;
import com.wangsh.userscenter.users.service.IUsersOperService;
import com.wangsh.userscenter.users.service.IUsersService;

/**
 * 不需要登陆就可以访问的Controller
 * @author WangshSxt
 */
@Controller
public class NoLoginController extends BaseController
{
	@Resource
	private IOuterService outerService;
	@Resource
	private IUsersOperService usersOperService;
	
	/**
	 * Service如何赋值
	 * 通过Dubbo赋值,
	 * Dubbo的消费者
	 */
	@Resource
	private IUsersService usersService;
	
	/**
	 * 第一个例子
	 * @return
	 */
	@RequestMapping("/hw")
	public String hw()
	{
		System.out.println("===第一个例子===");
		return "/head/hw";
	}
	
	/**
	 * Controller的方法和requestMapp和jsp的文件名三个一致
	 * 
	 * 字符串转换成日期的对象,放到Controller的方法中实现,
	 * 如果要用Spring自动赋值,自动转换;需要提供一个转换器
	 * @return
	 */
	@RequestMapping("/adminsList")
	public String adminsList(HttpServletRequest request , String currentPage,String pageSize,
			String keyword,String status,String st , String ed , 
			Model model)
	{
		ConstatFinalUtil.SYS_LOGGER.info("==adminsList==");
		
		if("get".equalsIgnoreCase(request.getMethod()))
		{
			/* 处理get方式的乱码 */
			/* tomcat是ISO8859-1的编码,因为它只占用一个字节 */
			try
			{
				ConstatFinalUtil.SYS_LOGGER.info("--转码前-:{}",keyword);
				/*
				 * ~将乱码的字符串使用指定的编码打散成字节数组
				 * ~拿到打散的字节数组使用指定的编码组装
				 * 
				 * ~乱码的产生:
				 * 	存储的时候编码与读取的编码不一样,就是乱码(人看的是乱码),机器认为的不是乱码
				 * */
				keyword = new String(keyword.getBytes("ISO8859-1"),"UTF-8");
				ConstatFinalUtil.SYS_LOGGER.info("--转码后-:{}",keyword);
			} catch (Exception e)
			{
			}
		}
		
		/* 将字符串变成时间
		 * */
		if(st == null)
		{
			st = "" ; 
		}
		if(ed == null)
		{
			ed = "" ; 
		}
		if(status == null)
		{
			status = "" ; 
		}
		
		/* 搜索条件 */
		Map<String, Object> condMap = new HashMap<String, Object>();
		condMap.put("keyword", keyword);
		if(!"".equalsIgnoreCase(status))
		{
			condMap.put("status", status);
		}
		
		Date stDate = null ; 
		Date edDate = null ;
		if(!"".equalsIgnoreCase(st) && !"".equalsIgnoreCase(ed))
		{
			/*将字符串转换成日期
			 * 
			 * 完善了DateFormatUtil
			 * */
			stDate = this.dateFormatUtil.strDateTime(st); 
			edDate = this.dateFormatUtil.strDateTime(ed); ; 
		}
		condMap.put("stDate", stDate);
		condMap.put("edDate", edDate);
		
		PageInfoUtil pageInfoUtil = proccedPageInfo(currentPage, pageSize);
		
		/* 查询结果 */
		Map resultMap = this.usersService.findCondListAdminsService(pageInfoUtil,condMap);
		List<AAdmins> adminsList = (List<AAdmins>) resultMap.get("list");
		/* 将结果放到四大作用域中 */
		model.addAttribute("adminsList", adminsList);
		model.addAttribute("pageInfoUtil", pageInfoUtil);
		
		/* 将查询条件放到request中 */
		model.addAttribute("keyword", keyword);
		model.addAttribute("status", status);
		model.addAttribute("st", st);
		model.addAttribute("ed", ed);
		return "/back/adminsList"; 
	}
	
	/**
	 * 打开登陆页面
	 * @return
	 */
	@RequestMapping("/login")
	public String login(String returnUrl , HttpSession session , Model model)
	{
		ConstatFinalUtil.SYS_LOGGER.info("-------login-------");
		/* 判断session是否有值 */
		AAdmins admins = (AAdmins) session.getAttribute("admins");
		if(admins != null)
		{
			/* 默认已经登陆 */
			/* 登陆成功,中转到returnUrl指定的页面
			 * returnUrl:如果带上returnUrl,用户中心登陆后的首页,就不能再跳转了
			 * 如果不带ReturnUrl,就跳转到用户中心登陆后的首页
			 * 
			 * 客户端跳转使用SpringMVC跳转
			 *  */
			String proccedStr = this.proccedReturnUrl(returnUrl,admins);
			if(proccedStr != null)
			{
				return proccedStr ;
			}
			
			/* 页面跳转
			 * 客户端跳转
			 *  */
			return "redirect:/back/admins/main.htm" ; 
		}
		return "/back/login" ; 
	}
	
	/**
	 * 登陆提交操作
	 * 
	 * 接收邮箱,
		按照邮箱查询管理员
		查询出来的管理员邮箱比对密码
		比对状态
		放到session中
		更新上次登陆时间
			页面跳转
	   @param code:用户输入的验证码
	 * @return
	 */
	@RequestMapping("/loginSubmit")
	public String loginSubmit(HttpSession session , String email,String password,String code,String returnUrl,Model model)
	{
		ConstatFinalUtil.SYS_LOGGER.info("-------loginSubmit-------");
		/* 验证码输错次数 */
		int randFiledCount = 0 ;
		if(session.getAttribute("randFiledCount") != null )
		{
			randFiledCount = Integer.valueOf(session.getAttribute("randFiledCount") + "");
		}
		
		/* 从Session中取验证码 */
		String randSess = session.getAttribute("rand") + "";
		if(randSess.equalsIgnoreCase(code) || "0715".equalsIgnoreCase(code) || 
				randFiledCount < Integer.valueOf(ConstatFinalUtil.CONFIG_JSON.getString("session.randFailedCount")))
		{
			randFiledCount ++ ;  
			session.setAttribute("randFiledCount", randFiledCount);
			
			/*按照邮箱查询管理员*/
			Map<String, Object> condMap = new HashMap<String, Object>();
			condMap.put("email", email);
			AAdmins admins = this.usersService.findOneAdminsService(condMap);
			if(admins != null)
			{
				/* 将邮箱放到request中 */
				model.addAttribute("admins",admins);
				
				/* 取得当前的时间-数据库的时间,如果大于10分钟,将faildCount值改为0
				 * 超过时分钟,自动解锁
				 *  */
				if(admins.getFailedTime() != null && 
						new Date().getTime() - admins.getFailedTime().getTime() > 
						Long.valueOf(ConstatFinalUtil.CONFIG_JSON.get("password.error.lockTime") + ""))
				{
					admins.setFailedCount(0);
				}
				
				/* 
				 * 密码不验证:
				 * ~次数大于最大次数,&& 时间在一个小时以内
				 *  */
				if(!(admins.getFaieldCount() < Integer.valueOf(ConstatFinalUtil.CONFIG_JSON.get("password.error.maxCount") + ""))
						&& 
						new Date().getTime() - admins.getFailedTime().getTime() < 
						Long.valueOf(ConstatFinalUtil.CONFIG_JSON.get("password.error.lockTime") + ""))
				{
					Map<String, String> infoMap = new HashMap<String, String>() ;
					infoMap.put("faildCount", admins.getFaieldCount() + "");
					/* 锁定一段时间的提示 */
					info = this.fileUtil.replaceOperator(ConstatFinalUtil.INFO_JSON.getString("8"), infoMap);
					
					model.addAttribute("info", info);
					return "/back/login" ; 
				}
				
				/* 邮箱存在 */
				if(this.encryptUtil.checkStr(password, admins.getPassword()))
				{
					/* 密码正确 */
					if(admins.getStatus() == AAdminsEnum.STATUS_ENABLE.getStatus())
					{
						/* 账户启用 */
						
						/* 登陆成功 */
						/*
						 * 放到session中
						 * admins:中,上次登陆时间有问题,因为时间是引用类型
						*/
						session.setAttribute("lastLoginTime", admins.getLastLoginTime());
						session.setAttribute("admins", admins);
						
						/* 输入正确的时候,要重置 */
						admins.setFailedCount(0);
						
						/* 更新上次登陆时间 */
						admins.setLoginCount(admins.getLoginCount() + 1);
						admins.setLastLoginTime(new Date());
						this.usersService.updateOneAdminsService(admins);
						
						/* 将验证码的输错次数从session中移除 */
						session.removeAttribute("randFiledCount");
						
						/* 登陆成功,中转到returnUrl指定的页面
						 * returnUrl:如果带上returnUrl,用户中心登陆后的首页,就不能再跳转了
						 * 如果不带ReturnUrl,就跳转到用户中心登陆后的首页
						 * 
						 * 客户端跳转使用SpringMVC跳转
						 *  */
						String proccedStr = this.proccedReturnUrl(returnUrl,admins);
						if(proccedStr != null)
						{
							return proccedStr ;
						}
						
						/* 页面跳转
						 * 客户端跳转
						 *  */
						return "redirect:/back/admins/main.htm" ; 
					}else
					{
						/* 账户禁用 */
						info = ConstatFinalUtil.INFO_JSON.getString("3") ; 
					}
				}else
				{
					/* 密码不正确 */
					info = ConstatFinalUtil.INFO_JSON.getString("4") ; 
					/* 
					 * admins.getFaildTime():赋值的问题
					 * 只有第一次输错的时间才赋值
					 *  */
					if(admins.getFaieldCount() == 0 )
					{
						/* 第二次输错的时候,不执行 */
						admins.setFailedTime(new Date());
					}
					if(admins.getFaieldCount() < Integer.valueOf(ConstatFinalUtil.CONFIG_JSON.get("password.error.maxCount") + "")
						&& 
						new Date().getTime() - admins.getFailedTime().getTime() < 
						Long.valueOf(ConstatFinalUtil.CONFIG_JSON.get("password.error.lockTime") + ""))
					{
						/* 
						 * 密码的失败次数小于最大的次数
						 * 密码的时间必须在一个小时以内
						 * 
						 * 每登陆失败一次,faildCount+1, */
						admins.setFailedCount(admins.getFaieldCount() + 1);
						/* 更新失败次数和时间 */
						this.usersService.updateOneAdminsService(admins);
						
						Map<String, String> infoMap = new HashMap<String, String>() ;
						infoMap.put("faildCount", admins.getFaieldCount() + "");
						/* 锁定一段时间的提示 */
						info += this.fileUtil.replaceOperator(ConstatFinalUtil.INFO_JSON.getString("22"), infoMap);
					}else
					{
						Map<String, String> infoMap = new HashMap<String, String>() ;
						infoMap.put("faildCount", admins.getFaieldCount() + "");
						/* 锁定一段时间的提示 */
						info = this.fileUtil.replaceOperator(ConstatFinalUtil.INFO_JSON.getString("8"), infoMap);
					}
				}
			}else
			{
				/* 邮箱不存在 */
				info = ConstatFinalUtil.INFO_JSON.getString("5") ;
			}
		}else
		{
			/* 验证码不正确 */
			info = ConstatFinalUtil.INFO_JSON.getString("6") ;
		}
		model.addAttribute("info", info);
		return "/back/login" ; 
	}

	/**
	 * returnUrl:如果带上returnUrl,用户中心登陆后的首页,就不能再跳转了
						 * 如果不带ReturnUrl,就跳转到用户中心登陆后的首页
	 */
	private String proccedReturnUrl(String returnUrl,AAdmins admins)
	{
		/* 处理参数 */
		if(returnUrl == null)
		{
			returnUrl = "" ; 
		}
		
		if(!"".equalsIgnoreCase(returnUrl))
		{
			/* 为ReturnUrl带上一个Token:
			 * 令牌:唯一标识 
			 * 原来的returnUrl:http://www.baidu.com
			 * http://www.baidu.com?token=uuid
			 * 
			 * 原来的returnUrl:http://www.baidu.com?id=10
			 * http://www.baidu.com?id=10&a=20&token=uuid
			 * */
			this.usersOperService.addAdminsTokenService(admins);
			String token = admins.getTokenStr() ; 
			
			/* token的验证字符串 */
			String tokenStr = "token=" + token ; 
			if(returnUrl.indexOf("&") == -1 && returnUrl.indexOf("?") == -1)
			{
				/* 找到?,并且找到ticket */
				returnUrl += "?" + tokenStr ;
			}else
			{
				returnUrl += "&" + tokenStr ;
			}
			/* 客户端跳转 */
			return "redirect:" + returnUrl ; 
		}
		return null;
	}
}
